//! # Serde2File
//!
//! ---
//!
//! serialize some data to a file or deserialize a data from a file by serde_json
//!
//! 1. Support:
//!
//! * Encrypted storage is supported when storing files
//! * Support user-defined encryption method and parameter transfer
//! * Provide default aes256gsm encryption implementation
//! * Flexible file storage location
//!
//! 2. derive macro [Serde2File](https://crates.io/crates/serde2file_macro_derive) Attributes（Optional）:
//!
//! ## usage
//!
//! ```ignore
//! #[derive(Serialize, Deserialize, Serde2File)]
//! #[serde2file(
//!     encrypt = "TestEncryptTool::encrypt",
//!     decrypt = "TestEncryptTool::decrypt",
//!     crypt_arg_type = "&'static str",
//!     file_name_getter_arg_type = "(&str,&str)",
//!     file_name_getter = "(&str,&str)",
//!     dump_file_name = "test_data.json",   
//!     file_name_getter = "some_get_file_name_function",
//!     file_name_getter_arg_type = "String"
//! )]
//! ```
//!
//! ## Attributes :
//!
//! * #[serde2file(arg1=value1,...)]
//!   * encrypt Data encryption method
//!   * decrypt Data decryption method
//!   * The above encryption and decryption methods must be set at the same time, otherwise encryption and decryption will not be performed.
//!   * example : #[serde2file(encrypt="TestEncryptTool::encrypt",decrypt="TestEncryptTool::decrypt")]
//!   * dump_file_name
//!     * Custom dump file name
//!     * If not set ,the default dump file name is the full name of the current Struct.
//!     * For example, the default dump file name corresponding to serde2file::test::TestData is serde2file-test-TestData.json
//!     * example : #[serde2file(dump_file_name = "test_data.json")]
//!   * crypt_arg_type
//!     * Define additional encryption and decryption parameter types
//!     * Used to pass custom parameters to encryption or decryption functions
//!     * example : #[serde2file(crypt_arg_type = "&'static str")]
//!   * Dynamically determine the file name and save path
//!     * file_name_getter : File name personalization acquisition function
//!     * file_name_getter_arg_type : File name acquisition function parameter type, used to dynamically obtain file name according to parameters
//!
//! 3. Features
//!
//! * default : core + encrypt_tool
//! * core : without encrypt_tool
//! * encrypt_tool : a Aes256Gcm crypt tool
//!
//! ---
//!
//! 将struct序列化化存储为文件，或者从文件反序列化为struct
//!
//!
//!
//! 1. 支持：
//!
//! * 文件存储时支持加密存储
//! * 支持自定义加密方法和参数传递
//! * 提供默认的aes256gsm加密实现
//! * 灵活的文件存储路径和名称设置
//!
//! 2. 派生宏[Serde2File](https://crates.io/crates/serde2file_macro_derive)属性(可选)
//!
//! ## 用法
//!
//! ```ignore
//! #[derive(Serialize, Deserialize, Serde2File)]
//! #[serde2file(
//!     encrypt = "TestEncryptTool::encrypt",
//!     decrypt = "TestEncryptTool::decrypt",
//!     crypt_arg_type = "&'static str",
//!     file_name_getter_arg_type = "(&str,&str)",
//!     file_name_getter = "(&str,&str)",
//!     dump_file_name = "test_data.json",   
//!     file_name_getter = "some_get_file_name_function",
//!     file_name_getter_arg_type = "String"
//! )]
//! ```
//!
//! ## 属性 :
//!
//! * #[serde2file(参数1=值1,...)]
//!   * encrypt 数据加密方法
//!   * decrypt 数据解密方法
//!   * 以上加密和解密方法必须同时设置，否则不进行加解密。
//!   * 例如：#[file_encrypt(encrypt="TestEncryptTool::encrypt",decrypt="TestEncryptTool::decrypt")]
//!   * dump_file_name
//!     * 设置自定义的转储文件名称
//!     * 自定义转储文件名称
//!     * 默认为当前Struct的完整名称，
//!     *  如serde2file::test::TestData对应的缺省转储文件名称为serde2file-test-TestData.json
//!     * 例如：#[serde2file(dump_file_name = "test_data.json")]
//!   * crypt_arg_type
//!     * 定义额外的加解密参数类型
//!     * 用于向加密或解密函数传递自定义参数使用
//!     * 例如：#[serde2file(crypt_arg_type = "&'static str")]
//!   * 动态确定文件名称和保存路径
//!     * file_name_getter 文件名称获取函数
//!     * file_name_getter_arg_type 文件名称获取函数传参类型，用于根据参数动态获取文件名称
//!     * 例如：#[serde2file(file_name_getter = "some_get_file_name_function",file_name_getter_arg_type = "String")]
//!
//!
//! 3. 特性
//!
//! * 默认 : core + encrypt_tool
//! * core 无加密工具
//! * encrypt_tool : Aes256Gcm 加密工具
//!
//! 4. Example / 示例
//!
//! (1) Simplest use / 最简单用法
//!
//! Without encryption, dump the struct directly to a json file. The dump file name is the default name
//!
//! 无需加密，直接将struct转储到json文件,转储文件名称为默认名称
//!
//! ```ignore
//! use serde::{Deserialize, Serialize};
//! use serde2file::prelude::*;
//!
//! #[derive(Debug, Serialize, Deserialize, Default, PartialEq, Eq, Serde2File)]
//! struct TestData {
//!     id: String,
//!     name: String,
//! }
//! #cfg(test)
//! mod test {
//!     use super::*;
//!     /// Test serialization and encrypted storage to file
//!     ///
//!     /// 测试序列化并加密存储到文件
//!     #[test]
//!     fn test_serialize_to_file() {
//!         let data = TestData {
//!             id: "01".into(),
//!             name: "hy".into(),
//!         };
//!         assert_eq!("/tmp/[package-name]-Test-Data.json",
//!             data.dump2file("/tmp").unwrap());
//!     }
//!     /// Test deserialization from encrypted file
//!     ///
//!     /// 测试从加密文件反序列化
//!     #[test]
//!     fn test_deserialize_from_file() {
//!         let data = TestData {
//!             id: "01".into(),
//!             name: "hy".into(),
//!         };
//!         let s_data = TestData::load_from_file("/tmp").unwrap();
//!         assert_eq!(data, s_data)
//!     }
//! }
//! ```
//!
//! (2) Encrypted dump to custom file / 加密转储为自定义文件
//!
//! Encrypt the dump file. The default aes256gsm encryption is used for encryption.   
//! No additional encryption parameters are required.   
//! Set the dump file name to test_ data.json.
//!
//! 加密转储文件，加密时使用默认的aes256gsm加密实现，无需额外加密参数,设置转储文件名称为test_data.json.
//!
//! ```ignore
//! use serde::{Deserialize, Serialize};
//! use serde2file::encrypt::Aes256GcmEncryptUtil;
//! use serde2file::prelude::*;
//!
//! #[allow(dead_code)]
//! #[derive(Debug, Serialize, Deserialize, Default, PartialEq, Eq, Serde2File)]
//! #[serde2file(
//!     dump_file_name = "test_data.json",
//!     encrypt = "TestEncryptTool::encrypt",
//!     decrypt = "TestEncryptTool::decrypt"
//! )]
//! struct TestData {
//!     id: String,
//!     name: String,
//! }
//! /// a encryption and decryption tools
//! #[allow(dead_code)]
//! struct TestEncryptTool;
//! impl Aes256GcmEncryptUtil for TestEncryptTool{
//!     type CryptArgType = ();
//!     fn get_aes_key_nonce(extra:Option<Self::CryptArgType>) -> (String, String) {
//!         (
//!             format!("*)_#@{}!$=_^20230208)leb*$xz",extra.unwrap_or("140600")),
//!             "abc$hy%95599".into(),
//!         )
//!     }
//! }
//!
//! /// Test serialization and encrypted storage to file
//! /// 测试序列化并加密存储到文件
//! #[test]
//! fn test_serde_file() {
//!     let data = TestData {
//!         id: "01".into(),
//!         name: "hy".into(),
//!     };
//!     assert_eq!("/tmp/test_data.json",data.dump2file("/tmp").unwrap());
//!     let s_data = TestData::load_from_file("/tmp").unwrap();
//!     assert_eq!(data, s_data)
//! }
//!
//! ```
//!
//!
//! (3) 自定义加密参数加密转储文件
//!
//! The default aes256gsm encryption is used for encryption,
//! and additional encryption and decryption parameters are required.
//! Set the dump file name to test_ data.json.
//!
//! 加密时使用默认的aes256gsm加密实现，并需要额外加解密参数,设置转储文件名称为test_data.json
//!
//!
//! ```ignore
//! use serde::{Deserialize, Serialize};
//! use super::encrypt::Aes256GcmEncryptUtil;
//! use crate::prelude::*;
//!
//! #[allow(dead_code)]
//! #[derive(Debug, Serialize, Deserialize, Default, PartialEq, Eq, Serde2File)]
//! #[serde2file(
//!     dump_file_name = "test_data2.json",
//!     encrypt = "TestEncryptTool::encrypt",
//!     decrypt = "TestEncryptTool::decrypt",
//!     crypt_arg_type = "&'static str"
//! )]
//! struct TestData2 {
//!     id: String,
//!     name: String,
//! }
//!
//! /// a encryption and decryption tools
//! #[allow(dead_code)]
//! struct TestEncryptTool;
//! impl Aes256GcmEncryptUtil for TestEncryptTool{
//!     type CryptArgType = &'static str;
//!     fn get_aes_key_nonce(extra:Option<Self::CryptArgType>) -> (String, String) {
//!         (
//!             format!("*)_#@{}!$=_^20230208)leb*$xz",extra.unwrap_or("140600")),
//!             "abc$hy%95599".into(),
//!         )
//!     }
//! }
//!
//! /// Test serialization and encrypted storage to file with extra param
//! /// 测试序列化并加密存储到文件
//! #[test]
//! fn test_serde_file() {
//!     let data = TestData2 {
//!         id: "01".into(),
//!         name: "hy".into(),
//!     };
//!     let file_name_arg = String::from("14H701");
//!     assert_eq!("/tmp/test_data2.json",data.dump2file_with_encrypt_arg("/tmp",Some("14H701"),Some(file_name_arg)).unwrap());
//!     let s_data = TestData2::load_from_file_with_decrypt_arg("/tmp",Some("14H701"),Some(file_name_arg)).unwrap();
//!     assert_eq!(data, s_data)
//! }
//!
//! ```
//!
//! (4) 自定义加密参数加密转储文件,并动态确定文件存储名称
//!
//! The default aes256gsm encryption is used for encryption,
//! and additional encryption and decryption parameters are required.
//! get the dump file name by get_file_name.
//!
//! 加密时使用默认的aes256gsm加密实现，并需要额外加解密参数,通过get_file_name函数获取文件名称
//!
//!
//! ```ignore
//! use serde::{Deserialize, Serialize};
//! use super::encrypt::Aes256GcmEncryptUtil;
//! use crate::prelude::*;
//!
//! fn get_file_name(sys_root:&str,extra:Option<String>) -> DumpResult<String>{
//!     Ok(format!("{sys_root}/{}",extra.unwrap()))
//! }
//!
//! #[allow(dead_code)]
//! #[derive(Debug, Serialize, Deserialize, Default, PartialEq, Eq, Serde2File)]
//! #[serde2file(
//!     encrypt = "TestEncryptTool::encrypt",
//!     decrypt = "TestEncryptTool::decrypt",
//!     crypt_arg_type = "&'static str"，
//!     file_name_getter = "get_file_name",
//!     file_name_getter_arg_type = "String"
//! )]
//! struct TestData2 {
//!     id: String,
//!     name: String,
//! }
//!
//! /// a encryption and decryption tools
//! #[allow(dead_code)]
//! struct TestEncryptTool;
//! impl Aes256GcmEncryptUtil for TestEncryptTool{
//!     type CryptArgType = &'static str;
//!     fn get_aes_key_nonce(extra:Option<Self::CryptArgType>) -> (String, String) {
//!         (
//!             format!("*)_#@{}!$=_^20230208)leb*$xz",extra.unwrap_or("140600")),
//!             "abc$hy%95599".into(),
//!         )
//!     }
//! }
//!
//! /// Test serialization and encrypted storage to file with extra param
//! /// 测试序列化并加密存储到文件
//! #[test]
//! fn test_serde_file_extra2() {
//!     let data = TestData2 {
//!         id: "01".into(),
//!         name: "hy".into(),
//!     };
//!
//!     let file_name_arg = String::from("14H701");
//!     assert_eq!(
//!         format!("/tmp/{fiel_name_arg}"),
//!         data.dump2file_with_encrypt_arg_and_path(
//!             "/tmp",
//!             Some("14H701"),
//!             Some(file_name_arg)
//!         ).unwrap());
//!     let s_data = TestData2::load_from_file_with_decrypt_arg_and_path("/tmp",Some("14H701"),Some(file_name_arg)).unwrap();
//!     assert_eq!(data, s_data)
//! }
//!
//! ```

use serde::{Deserialize, Serialize};
use std::{fmt::Display, fs, path::Path};

/// Encryption method type
///
/// * T is an additional encryption parameter, which is used to pass any parameter to the encryption function
///
/// ---
///
/// 加密方法类型
///
/// * T 为额外的加密参数，用于向加密函数传递任意参数，类型需要与FileSerde::CryptExtraArgType一致
pub type EncryptMethod<T> = fn(&str, Option<T>) -> DumpResult<Vec<u8>>;

/// Decryption method type
///
/// * T is an additional decryption parameter, which is used to pass any parameter to the decryption function
///
/// ---
///
/// 解密方法类型
///
/// * T 为额外的解密参数，用于向解密函数传递任意参数，类型需要与FileSerde::CryptExtraArgType一致
///
pub type DecryptMethod<T> = fn(Vec<u8>, Option<T>) -> DumpResult<Vec<u8>>;

/// File Name Personalization Getter's Type
///
/// * T Generate personalized parameters for file name and path.
///   * The type should be consistent with FileSerde:: FileNameGetterArgType
///
/// ---
///
/// 文件名称个性化获取器类型
///
/// * T 生成文件名称和路径的个性化参数，类型需要与FileSerde::FileNameGetterArgType一致
pub type FileNameGetter<T> = fn(&str, Option<T>) -> DumpResult<String>;

#[derive(Debug)]
pub enum DumpError {
    /// I/O 错误
    IOError(std::io::Error),
    /// 加密错误
    EncryptErr(String),
    /// 解密错误
    DecryptError(String),
    /// 序列化错误
    SerializeError(serde_json::Error),
    /// 其他错误
    OtherError(String),
}

impl std::error::Error for DumpError {}

impl From<DumpError> for String {
    fn from(value: DumpError) -> Self {
        value.to_string()
    }
}

impl Display for DumpError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            DumpError::IOError(err) => write!(f, "IO Error/IO 错误：{:?}", err),
            DumpError::EncryptErr(err) => write!(f, "Encrypt Error/加密 错误：{}", err),
            DumpError::DecryptError(err) => write!(f, "Decrypt Error/解密 错误：{}", err),
            DumpError::SerializeError(err) => write!(f, "Serialize Error/序列化 错误：{:?}", err),
            DumpError::OtherError(err) => write!(f, "Other Error/其他 错误：{}", err),
        }
    }
}

impl From<serde_json::Error> for DumpError {
    fn from(value: serde_json::Error) -> Self {
        DumpError::SerializeError(value)
    }
}

impl From<std::io::Error> for DumpError {
    fn from(value: std::io::Error) -> Self {
        DumpError::IOError(value)
    }
}

/// serialization or deserialization error
///
/// 序列号或者反序列化错误
pub type DumpResult<T> = Result<T, DumpError>;

/// A data structure that can be serialized and dumped to a file
///
/// 某个可以并序列化并转储到文件的结构
pub trait FileSerde
where
    Self: Serialize + for<'a> Deserialize<'a>,
{
    /// Additional parameter types for cryptographic functions
    ///
    /// 加密函数的额外参数类型
    type CryptExtraArgType;

    /// Optional file encryption method
    ///
    /// 可选的文件加密方法
    const ENCRYPT: Option<EncryptMethod<Self::CryptExtraArgType>>;

    /// Optional file decryption method
    ///
    /// 可选的文件解密方法
    const DECRYPT: Option<DecryptMethod<Self::CryptExtraArgType>>;

    /// Custom dump file name
    ///
    /// The default dump file name is the full name of the current Struct.
    ///
    /// For example, the default dump file name corresponding to serde2file::test::TestData is serde2file-test-TestData.json
    ///
    /// ---
    ///
    /// 自定义转储文件名称
    ///
    /// 如未设置,默认为当前Struct的完整名称，
    ///
    /// 如serde2file::test::TestData对应的缺省转储文件名称为serde2file-test-TestData.json
    ///
    const DUMP_FILE_NAME: Option<&'static str>;

    /// Personalized file name parameter type, used to customize the saved file name
    /// must be set at the same time as Self::FILE_NAME_GETTER.
    ///
    /// 个性化文件名称参数类型，用于自定义保存文件名称，与FILE_NAME_GETTER共同使用
    type FileNameGetterArgType;

    /// Optional file name personalization acquisition function must be set at the same time as Self::FileNameArgType.
    ///
    /// 可选的文件名称个性化获取函数，必须与FileNameArgType同时设定。
    const FILE_NAME_GETTER: Option<FileNameGetter<Self::FileNameGetterArgType>>;

    ///
    /// If you need to implement flexible storage of file directories and names,
    /// you can implement this method and_ file_ name_ Arg carries out personalized parameter transfer.
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    /// * _file_name_arg custom file name parameters
    ///
    /// ---
    ///
    /// 获取转储文件的完整路径
    ///
    /// 默认实现：存储文件路径为save_path/file_name,如果对应目录不存在，则自动创建
    ///
    /// 如果需要实现灵活的存储文件目录和名称，可实现该方法，并通过_file_name_arg进行个性化传参。
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    /// * file_name_arg 个性化文件名称参数
    ///
    fn get_save_file_name(
        &self,
        save_path: &str,
        file_name_arg: Option<Self::FileNameGetterArgType>,
    ) -> Result<String, DumpError> {
        let file_path = Self::get_load_file_name(save_path, file_name_arg)?;
        let save_path = Path::new(&file_path)
            .parent()
            .expect("get store path failed.");
        if !save_path.exists() {
            fs::create_dir_all(save_path)?;
        }
        Ok(file_path)
    }

    /// Get the full path of the dump file.
    ///
    /// Default implementation:
    ///
    /// Call Self::get_load_file_Name gets the storage file path,
    /// If the file storage directory does not exist, it will be automatically created.
    ///
    /// If you need to implement flexible storage of file directories and names,
    /// you can implement this method and_ file_ name_ Arg carries out personalized parameter transfer.
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    /// * _file_name_arg custom file name parameters
    ///
    /// ---
    ///
    /// 获取转储文件的完整路径
    ///
    /// 默认实现：
    ///
    /// 调用Self::get_load_file_name获取存储文件路径，如果该文件存储目录不存在，则自动创建。
    ///
    /// 如果需要实现灵活的存储文件目录和名称，可实现该方法，并通过_file_name_arg进行个性化传参。
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    /// * file_name_arg 个性化文件名称参数
    ///
    fn get_load_file_name(
        save_path: &str,
        file_name_arg: Option<Self::FileNameGetterArgType>,
    ) -> Result<String, DumpError> {
        let file_path = if let Some(file_name_getter) = Self::FILE_NAME_GETTER {
            file_name_getter(save_path, file_name_arg)?
        } else if let Some(dump_file_name) = Self::DUMP_FILE_NAME {
            format!("{save_path}/{dump_file_name}")
        } else {
            format!(
                "{save_path}/{}.json",
                std::any::type_name::<Self>().replace("::", "-")
            )
        };
        Ok(file_path)
    }

    /// Dump data to a file.
    ///
    /// # Encryption Description
    ///
    /// * If Self:: ENCRYPT is not equal to None, the Self:: ENCRYPT function is called to encrypt and store the data.
    ///
    /// # Storage file location
    ///
    /// * Default is save_path/Self::DUMP_FILE_NAME
    /// * If Self:: FILE_ NAME_ If GETTER is not equal to None, call Self:: FILE_ NAME_ GETTER (save_path, None) Get the full path of the file
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    ///
    /// # Return
    ///
    /// return the saved file's full path.
    ///
    /// ---
    ///
    /// 将数据转储到文件。
    ///
    /// # 加密说明
    ///
    /// * 如果Self::ENCRYPT不等于None，则调用Self::ENCRYPT函数对数据进行加密后存储。
    ///
    /// # 存储文件位置
    ///
    /// * 默认为save_path/Self::DUMP_FILE_NAME
    /// * 如果Self::FILE_NAME_GETTER不等于None,则调用Self::FILE_NAME_GETTER(save_path,None)获取文件完整路径
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    ///
    /// # 返回说明
    ///
    /// 返回成功转储的文件完整路径.
    ///
    fn dump2file<P: AsRef<Path>>(&self, save_path: P) -> DumpResult<String> {
        self.dump2file_with_encrypt_arg(save_path, None)
    }

    /// Dump data to a file with custom path.
    ///
    /// # Encryption Description
    ///
    /// * If Self:: ENCRYPT is not equal to None, the Self:: ENCRYPT function is called to encrypt and store the data.
    ///
    /// # Storage file location
    ///
    /// * Default is save_path/Self::DUMP_FILE_NAME
    /// * If Self:: FILE_ NAME_ If GETTER is not equal to None, call Self:: FILE_ NAME_ GETTER (save_path, None) Get the full path of the file
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    /// * file_name_arg : custom file name parameters
    ///
    /// # Return
    ///
    /// return the saved file's full path.
    ///
    /// ---
    ///
    /// 将数据转储到文件，文件名称动态确定。
    ///
    /// # 加密说明
    ///
    /// * 如果Self::ENCRYPT不等于None，则调用Self::ENCRYPT函数对数据进行加密后存储。
    ///
    /// # 存储文件位置
    ///
    /// * 默认为save_path/Self::DUMP_FILE_NAME
    /// * 如果Self::FILE_NAME_GETTER不等于None,则调用Self::FILE_NAME_GETTER(save_path,file_name_arg)获取文件完整路径
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    /// * file_name_arg 个性化文件名参数
    ///
    /// # 返回说明
    ///
    /// 返回成功转储的文件完整路径.
    ///
    fn dump2file_with_path<P: AsRef<Path>>(
        &self,
        save_path: P,
        file_name_arg: Option<Self::FileNameGetterArgType>,
    ) -> DumpResult<String> {
        self.dump2file_with_encrypt_arg_and_path(save_path, None, file_name_arg)
    }

    /// Dump data to a file with some extra encrypt parameter.
    ///
    ///
    /// # Encryption Description
    ///
    /// * If Self:: ENCRYPT is not None, the Self::ENCRYPT(data,encrypt_extra_arg) function is called to encrypt and store the data.
    ///
    /// # Storage file location
    ///
    /// * Default is save_path/Self::DUMP_FILE_NAME
    /// * If Self:: FILE_ NAME_ If GETTER is not None, call Self:: FILE_ NAME_ GETTER (save_path, None) Get the full path of the file
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    /// * encrypt_extra_arg : Additional encryption parameters
    ///
    /// # Return
    ///
    /// return the saved file's full path.
    ///
    /// ---
    ///
    /// 将数据转储到文件。
    ///
    /// # 加密说明
    ///
    /// * 如果Self::ENCRYPT不等于None，则调用Self::ENCRYPT(data,encrypt_extra_arg)函数对数据进行加密后存储。
    ///
    /// # 存储文件位置
    ///
    /// * 默认为save_path/Self::DUMP_FILE_NAME
    /// * 如果Self::FILE_NAME_GETTER不等于None,则调用Self::FILE_NAME_GETTER(save_path,None)获取文件完整路径
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    /// * encrypt_extra_arg 额外的加密参数
    ///
    /// # 返回说明
    ///
    /// 返回成功转储的文件完整路径.
    ///
    fn dump2file_with_encrypt_arg<P: AsRef<Path>>(
        &self,
        save_path: P,
        encrypt_extra_arg: Option<Self::CryptExtraArgType>,
    ) -> DumpResult<String> {
        self.dump2file_with_encrypt_arg_and_path(save_path, encrypt_extra_arg, None)
    }

    /// Dump data to a file with some extra encrypt parameter and with custom save path.
    ///
    /// # Encryption Description
    ///
    /// * If Self:: ENCRYPT is not None, the Self::ENCRYPT(data,encrypt_extra_arg) function is called to encrypt and store the data.
    ///
    /// # Storage file location
    ///
    /// * Default is save_path/Self::DUMP_FILE_NAME
    /// * If Self:: FILE_ NAME_ If GETTER is not None, call Self:: FILE_ NAME_ GETTER (save_path, file_name_arg) Get the full path of the file
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    /// * encrypt_extra_arg : Additional encryption parameters
    /// * file_name_arg : custom file name parameters
    ///
    /// # Return
    ///
    /// return the saved file's full path.
    /// If the directory where the file does not exist, it will be created automatically.
    ///
    /// ---
    ///
    /// 将数据转储到文件。
    ///
    /// # 加密说明
    ///
    /// * 如果Self::ENCRYPT不等于None，则调用Self::ENCRYPT(data,encrypt_extra_arg)函数对数据进行加密后存储。
    ///
    /// # 存储文件位置
    ///
    /// * 默认为save_path/Self::DUMP_FILE_NAME
    /// * 如果Self::FILE_NAME_GETTER不等于None,则调用Self::FILE_NAME_GETTER(save_path,file_name_arg)获取文件完整路径
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    /// * encrypt_extra_arg 额外的加密参数
    /// * file_name_arg 个性化文件名参数
    ///
    /// # 返回说明
    ///
    /// 返回成功转储的文件完整路径.
    /// 如果该文件所在目录不存在，将自动创建。
    ///
    fn dump2file_with_encrypt_arg_and_path<P: AsRef<Path>>(
        &self,
        save_path: P,
        encrypt_extra_arg: Option<Self::CryptExtraArgType>,
        file_name_arg: Option<Self::FileNameGetterArgType>,
    ) -> DumpResult<String> {
        let plain_str = serde_json::to_string_pretty(self)?;
        let data = if let Some(encrypt) = Self::ENCRYPT {
            encrypt(&plain_str, encrypt_extra_arg)?
        } else {
            plain_str.as_bytes().to_vec()
        };
        let save_path = save_path.as_ref();
        let save_path = save_path.to_str().ok_or_else(|| DumpError::OtherError(format!("转换路径{}为str失败!",save_path.display())))?;
        let save_file_name = self.get_save_file_name( save_path, file_name_arg)?;
        //let save_file_name = Self::get_load_file_name(save_path, file_name_arg)?;
        fs::write(&save_file_name, data)?;
        Ok(save_file_name)
    }

    /// reading and decrypting (optional) the stored file, and deserialized to a data structure
    ///
    /// # Decryption Description
    ///
    /// * If Self::DECRYPT is not None, the Self::DECRYPT(data,None) function is called to decrypt and store the data.
    ///
    /// # Storage file location
    ///
    /// * Default is save_path/Self::DUMP_FILE_NAME
    /// * If Self:: FILE_ NAME_ If GETTER is not None, call Self:: FILE_ NAME_ GETTER (save_path, None) Get the full path of the file
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    ///
    /// ---
    ///
    /// 读取并解密（可选）存储的文件后，反序列为对应数据结构
    ///
    /// # 解密说明
    ///
    /// * 如果Self::DECRYPT不等于None，则调用Self::DECRYPT(data,None)函数对数据进行解密。
    ///
    /// # 存储文件位置
    ///
    /// * 默认为save_path/Self::DUMP_FILE_NAME
    /// * 如果Self::FILE_NAME_GETTER不等于None,则调用Self::FILE_NAME_GETTER(save_path,None)获取文件完整路径
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    ///
    fn load_from_file<P: AsRef<Path>>(save_path: P) -> DumpResult<Self> {
        Self::load_from_file_with_decrypt_arg(save_path, None)
    }

    /// reading and decrypting (optional) the stored file, and deserialized to a data structure
    /// File name dynamic acquisition.
    ///
    /// # Decryption Description
    ///
    /// * If Self::DECRYPT is not None, the Self::DECRYPT(data,None) function is called to decrypt and store the data.
    ///
    /// # Storage file location
    ///
    /// * Default is save_path/Self::DUMP_FILE_NAME
    /// * If Self:: FILE_ NAME_ If GETTER is not None, call Self:: FILE_ NAME_ GETTER (save_path, file_name_arg) Get the full path of the file
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    /// * file_name_arg : custom file name parameters
    ///
    /// ---
    ///
    /// 读取并解密（可选）存储的文件后，反序列为对应数据结构，文件名称动态获取
    ///
    /// # 解密说明
    ///
    /// * 如果Self::DECRYPT不等于None，则调用Self::DECRYPT(data,None)函数对数据进行解密。
    ///
    /// # 存储文件位置
    ///
    /// * 默认为save_path/Self::DUMP_FILE_NAME
    /// * 如果Self::FILE_NAME_GETTER不等于None,则调用Self::FILE_NAME_GETTER(save_path,file_name_arg)获取文件完整路径
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    /// * file_name_arg 个性化文件名参数
    ///
    ///
    fn load_from_file_with_path<P: AsRef<Path>>(
        save_path: P,
        file_name_arg: Option<Self::FileNameGetterArgType>,
    ) -> DumpResult<Self> {
        Self::load_from_file_with_decrypt_arg_and_path(save_path, None, file_name_arg)
    }

    /// reading and decrypting (optional) the stored file,  
    /// and deserialized to a data structure with some extra encrypt parameter.
    ///
    /// # Decryption Description
    ///
    /// * If Self::DECRYPT is not None, the Self::DECRYPT(data,encrypt_extra_arg) function is called to decrypt and store the data.
    ///
    /// # Storage file location
    ///
    /// * Default is save_path/Self::DUMP_FILE_NAME
    /// * If Self:: FILE_ NAME_ If GETTER is not None, call Self:: FILE_ NAME_ GETTER (save_path, None) Get the full path of the file
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    /// * decrypt_extra_arg : Additional decryption parameters
    ///
    /// ---
    ///
    /// 读取并解密（可选）存储的文件后，反序列为对应数据结构
    ///
    /// # 解密说明
    ///
    /// * 如果Self::DECRYPT不等于None，则调用Self::DECRYPT(data,encrypt_extra_arg)函数对数据进行解密。
    ///
    /// # 存储文件位置
    ///
    /// * 默认为save_path/Self::DUMP_FILE_NAME
    /// * 如果Self::FILE_NAME_GETTER不等于None,则调用Self::FILE_NAME_GETTER(save_path,None)获取文件完整路径
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    /// * encrypt_extra_arg 额外的解密参数
    ///
    fn load_from_file_with_decrypt_arg<P: AsRef<Path>>(
        save_path: P,
        decrypt_extra_arg: Option<Self::CryptExtraArgType>,
    ) -> DumpResult<Self> {
        Self::load_from_file_with_decrypt_arg_and_path(save_path, decrypt_extra_arg, None)
    }

    /// After reading and decrypting (optional) the files in the stored personalized directory,
    /// the reverse sequence is the corresponding data structure.
    ///
    /// # Decryption Description
    ///
    /// * If Self::DECRYPT is not None, the Self::DECRYPT(data,encrypt_extra_arg) function is called to decrypt and store the data.
    ///
    /// # Storage file location
    ///
    /// * Default is save_path/Self::DUMP_FILE_NAME
    /// * If Self:: FILE_ NAME_ If GETTER is not None, call Self:: FILE_ NAME_ GETTER (save_path, file_name_arg) Get the full path of the file
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    /// * decrypt_extra_arg : Additional decryption parameters
    /// * file_name_arg : custom file name parameters
    ///
    /// ---
    ///
    /// 读取并解密（可选）存储的个性化目录中文件后，反序列为对应数据结构。
    ///
    /// # 解密说明
    ///
    /// * 如果Self::DECRYPT不等于None，则调用Self::DECRYPT(data,encrypt_extra_arg)函数对数据进行解密。
    ///
    /// # 存储文件位置
    ///
    /// * 默认为save_path/Self::DUMP_FILE_NAME
    /// * 如果Self::FILE_NAME_GETTER不等于None,则调用Self::FILE_NAME_GETTER(save_path,file_name_arg)获取文件完整路径
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    /// * encrypt_extra_arg 额外的解密参数
    /// * file_name_arg 个性化文件名参数
    ///
    fn load_from_file_with_decrypt_arg_and_path<P: AsRef<Path>>(
        save_path: P,
        decrypt_extra_arg: Option<Self::CryptExtraArgType>,
        file_name_arg: Option<Self::FileNameGetterArgType>,
    ) -> DumpResult<Self> {
        let plain_data = Self::get_deserialize_data(save_path, decrypt_extra_arg, file_name_arg)?;
        let data = serde_json::from_slice(&plain_data)?;
        Ok(data)
    }

    /// Read and decrypt (optional) files stored in reverse sequence
    ///
    /// # Parameters
    ///
    /// * save_path : Location where the dump file are stored
    /// * decrypt_extra_arg : Additional decryption parameters
    ///
    /// # Return
    ///
    /// Return decryption data
    ///
    /// ---
    ///
    /// 读取并解密（可选）反序列存储的文件
    ///
    ///
    /// # 参数说明
    ///
    /// * save_path 存储文件的位置
    /// * encrypt_extra_arg 额外的解密参数
    ///
    /// # 返回
    ///
    /// 返回解密后的数据
    fn get_deserialize_data<P: AsRef<Path>>(
        save_path: P,
        decrypt_extra_arg: Option<Self::CryptExtraArgType>,
        file_name_arg: Option<Self::FileNameGetterArgType>,
    ) -> DumpResult<Vec<u8>> {
        let save_path = save_path.as_ref();
        let save_path = save_path.to_str().ok_or_else(|| DumpError::OtherError(format!("转换路径{}为str失败!",save_path.display())))?;
        let save_file_name = Self::get_load_file_name(save_path, file_name_arg)?;
        let encrypt_data = fs::read(save_file_name)?;

        let plain_data = if let Some(decrypt) = Self::DECRYPT {
            decrypt(encrypt_data, decrypt_extra_arg)?
        } else {
            encrypt_data
        };
        Ok(plain_data)
    }
}

/// encryption tool
///
/// 加密工具,仅在encrypt_tool特性有效
#[cfg(feature = "encrypt_tool")]
pub mod encrypt;
/// 预加载类
pub mod prelude;
#[cfg(test)]
mod test;
